package graphicView;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.*;
import java.util.Observer;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import model.DiagramImpl;
import model.PackageEditor;

/**
 * Team EBE - Elite Bombard Elephants
 * 
 * DiagramUserInterface.java is the graphical user interface based off of Dr.
 * Hutchens' puzzle example, and modified to handle UML diagrams
 * 
 */
public class DiagramUserInterface extends JPanel implements ActionListener {

	private ActiveClassNotifier activeclassNotifier;
	private static final long serialVersionUID = 1L;
	private OutputStream os;
	
	private JFrame frame;
	private GraphicController controller;
	private JTextArea theOutputMessage;
	private DiagramImpl DI;
	private PackageEditor editor;

	private Vector<ClassGraphicObject> classesToDraw;
	private Vector<RelationshipGraphicObject> relationshipsToDraw;
	private Vector<PackageGraphicObject> packagesToDraw;
	
	
	private PackageGUI package1;
	
	private JPopupMenu contextMenu;

	MyPanel drawFrame;

	private JScrollPane JSP;
	private Graphics g;
	private PageFormat pf;
	private int i;
	
	private static final String newText = "New";
	private static final String saveMenuText = "Save UML";
	private static final String openMenuText = "Open UML";
	private static final String insertText = "Inspectors";
	private static final String classText = "Class Inspector";
	private static final String packageText = "Package Inspector";
	private static final String printText = "Print";
	private static final String relationText = "Relationship Inspector";
	private static final String helpText = "Help";
	private static final String helpText2 = "Package";
	private static final String helpText3 = "Class";
	private static final String helpText4 = "Relationship";
	private static final String exitText = "Exit";
	
	private int popupX, popupY;

	public DiagramUserInterface(GraphicController aController, JFrame aFrame,
			Vector<ClassGraphicObject> cgoIn,
			Vector<RelationshipGraphicObject> rgoIn,
			Vector<PackageGraphicObject> pgoIn,
			ActiveClassNotifier activeClassNotifierIn) {

		activeclassNotifier = activeClassNotifierIn;
		classesToDraw = cgoIn;
		relationshipsToDraw = rgoIn;
		packagesToDraw = pgoIn;
		frame = aFrame;
		controller = aController;
		JSP = setupLayout();
		drawFrame = new MyPanel(classesToDraw, relationshipsToDraw, packagesToDraw,
				activeclassNotifier, aController);
		activeclassNotifier.addObserver(drawFrame);
		createMenu(frame);
		createPopupMenu(contextMenu);

		frame.getContentPane().add(JSP, BorderLayout.CENTER);

		frame.getContentPane().add(drawFrame);
	}

	private void createMenu(JFrame frame2) {

		JMenuItem RelationItem, ClassItem, PackageItem;
		JMenu Insert, Help;

		// create a menu bar
		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);

		// create the File Item on the menu bar
		JMenu fileMenu = new JMenu("File");
		menuBar.add(fileMenu);

		// create the New submenu item and listen for it
		JMenuItem New = new JMenuItem(newText);
		New.addActionListener(this);
		fileMenu.add(New);

		fileMenu.addSeparator();
		
		// create the Open submenu item and listen for it
		JMenuItem Open = new JMenuItem(openMenuText);
		Open.addActionListener(this);
		fileMenu.add(Open);

		// create the Save submenu item and listen for it
		JMenuItem Save = new JMenuItem(saveMenuText);
		Save.addActionListener(this);
		fileMenu.add(Save);
		
		fileMenu.addSeparator();
		
		
		JMenuItem Print = new JMenuItem(printText);
		Print.addActionListener(this);
		fileMenu.add(Print);
		
		fileMenu.addSeparator();
		
		// create the Exit submenu item and listen for it
		JMenuItem Exit = new JMenuItem(exitText);
		Exit.addActionListener(this);
		fileMenu.add(Exit);

		// create the Edit Item on the menu bar
		JMenu editMenu = new JMenu("Edit");
		menuBar.add(editMenu);

	
		// create the Menu used by the Package, Class, and Relationship Inspectors 
		Insert = new JMenu(insertText);
		Insert.setMnemonic(KeyEvent.VK_S);
		Insert.addActionListener(this);
		editMenu.add(Insert);

		//create the Package Item submenu and listen for it 
		PackageItem = new JMenuItem(packageText);
		Insert.add(PackageItem);
		PackageItem.addActionListener(this);
	
		PackageItem.addActionListener(this);
		Insert.add(PackageItem);

		ClassItem = new JMenuItem(classText);
		Insert.add(ClassItem);
		ClassItem.addActionListener(this);

		RelationItem = new JMenuItem(relationText);
		Insert.add(RelationItem);
		RelationItem.addActionListener(this);

		editMenu.add(Insert);
		
		JMenu helpMenu = new JMenu("Help");
		menuBar.add(helpMenu);
		
		JMenuItem HelpItem = new JMenuItem(helpText2);
		helpMenu.add(HelpItem);
		HelpItem.addActionListener(this);
		
		JMenuItem HelpItem2 = new JMenuItem(helpText3);
		helpMenu.add(HelpItem2);
		HelpItem2.addActionListener(this);
		
		JMenuItem HelpItem3 = new JMenuItem(helpText4);
		helpMenu.add(HelpItem3);
		HelpItem3.addActionListener(this);

	}

	public void createPopupMenu(JPopupMenu theMenu) {
		JMenuItem menuItem, IpackItem, IclassItem, IrelItem, delItemR, delItemC, delItemP, EpackItem , EclassItem, ErelItem;

		// Create the popup menu.
		theMenu = new JPopupMenu();
		
		IpackItem = new JMenuItem("Insert Package");
		IpackItem.addActionListener(this);
		theMenu.add(IpackItem);
		
		IclassItem = new JMenuItem("Insert Class");
		IclassItem.addActionListener(this);
		theMenu.add(IclassItem);
		
		IrelItem = new JMenuItem("Insert Relationship");
		IrelItem.addActionListener(this);
		theMenu.add(IrelItem);
		
		
		delItemC = new JMenuItem("Delete Class");
		delItemC.addActionListener(this);
		theMenu.add(delItemC);
		
		delItemR = new JMenuItem("Delete Relationship");
		delItemR.addActionListener(this);
		theMenu.add(delItemR);
		
		delItemP = new JMenuItem("Delete Package");
		delItemP.addActionListener(this);
		theMenu.add(delItemP);
		
	
		EpackItem = new JMenuItem("Edit Package");
		EpackItem.addActionListener(this);
		theMenu.add(EpackItem);
		
		EclassItem = new JMenuItem("Edit Class");
		EclassItem.addActionListener(this);
		theMenu.add(EclassItem);
		
		ErelItem = new JMenuItem("Edit Relationship");
		ErelItem.addActionListener(this);
		theMenu.add(ErelItem);
	
	
		// Add listener to the text area so the popup menu can come up.
		MouseListener popupListener = new PopupListener(theMenu, this);
		drawFrame.addMouseListener(popupListener);
	}
	
	public void updatePopupLoc(int x, int y){
		popupX = x;
		popupY = y;
	}

	private JScrollPane setupLayout() {

		JPanel drawField = new JPanel();
		JScrollPane JS = new JScrollPane(drawField, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		
		setLayout(new BorderLayout());
		
		JS.createHorizontalScrollBar();
		JS.createVerticalScrollBar();

		drawField.setPreferredSize(new Dimension(1600, 800));
		drawField.setBorder(BorderFactory.createLineBorder(Color.gray, 2));

		return JS;
	}

	@Override
	public void actionPerformed(ActionEvent ae) {

		String command = ae.getActionCommand();
		
		if (command == insertText) {
			
		}else if (command == newText){
			controller.newDiagram();
		}else if (command == relationText) {
			controller.openRelation();
		} else if (command == packageText) {
			controller.openPackage();
		}
		else if (command == classText) {
			controller.openClass();
		}else if (command == saveMenuText){
			try {
				controller.saveDiagram();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else if (command == "Insert Class"){
			controller.addClass(popupX, popupY);
			repaint();
		} else if (command == "Insert Package"){
			controller.addPackage(popupX,popupY);
		} else if (command == "Insert Relationship"){
			drawFrame.setNewRelMode();
			drawFrame.redraw();
		} else if (command == "Delete Class"){
			for (ClassGraphicObject cgo: classesToDraw){
				if (popupX > cgo.getoX() && popupX < cgo.getoX() + cgo.getWidth() && popupY > cgo.getoY() && popupY < cgo.getoY() + cgo.getHeight()){
					controller.deleteClass(cgo);

					break;
				}
				drawFrame.redraw();
			}
		}else if (command == "Delete Relationship"){
			
			//???
				
		}else if (command == "Delete Package"){
			
			//???
				
		}else if (command == "Edit Package"){
			
			controller.openPackage();
				
		}else if (command == "Edit Class"){
			
			controller.openClass();
				
		}else if (command == "Edit Relationship"){
			
			controller.openRelation();
				
		}else if (command == printText){
			
				controller.print();  
		}
		else if (command == exitText){
		
			frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			System.exit(0);
			
		}
		else if(command == helpText2){
			
			JOptionPane.showMessageDialog(frame, "The package object can be created by right-clicking your mouse and left-clicking the (Insert Package) pop-up menuItem.\n"
					+ "Once inserted, the package can be moved/dragged to any desired location.\n"
					+ "You can edit a package by either using the Edit menu and selecting (Package Inspector), or by right-clicking on the package and left-clicking on the (Edit Package) pop-up menuItem.\n"
					+ "The Package's Name and/or size can be editted once in the (Package Inspector) frame.\n"
					+ "A Helpful Note: Editting package methods will effect the LAST PACKAGE CLICKED!!! \n"
					+ "For example: If you click on a package, any Editting method (by Edit menu, or right-click), will effect that package; even if you right-click anywhere else in the textarea, \n"
					+ "the LAST PACKAGE CLICKED (right-click or left-click), will be editted.\n"
					+ "Small Bug Note: Since the LAST PACKAGE CLICKED is the one editted, if a New Diagram is opened and no new package is inserted, a package in the previous program WILL BE EFFECTED!!\n",
					"Package Info", JOptionPane.PLAIN_MESSAGE);
		}
		else if(command == helpText3){
			
			JOptionPane.showMessageDialog(frame, "The class object can be created by right-clicking your mouse and left-clicking the (Insert Class) pop-up menuItem.\n"
					+ "Once inserted, the class can be moved/dragged to any desired location.\n"
					+ "You can edit a class by either using the Edit menu and selecting (Class Inspector), or by right-clicking on the class and left-clicking on the (Edit Class) pop-up menuItem.\n"
					+ "Once you are in the Class Inspector frame, you can add and/or delete operations (Names, Types, Visibilities) and attributes (Names, Types, Visibilities).\n"
					+ "A Helpful Note: Editting class methods will effect the LAST CLASS CLICKED!!! \n"
					+ "For example: If you click on a class, any Editting method (by Edit menu, or right-click), will effect that class; even if you right-click anywhere else in the textarea, \n"
					+ "the LAST CLASS CLICKED (right-click or left-click), will be editted.\n"
					+ "Small Bug Note: Since the LAST CLASS CLICKED is the one editted, if a New Diagram is opened and no new class is inserted, a class in the previous program WILL BE EFFECTED!!\n" ,
					"Class Info", JOptionPane.PLAIN_MESSAGE);
		}
		else if(command == helpText4){
	
			JOptionPane.showMessageDialog(frame, "The relationship object can be created by right-clicking your mouse and left-clicking the (Insert Relationship) pop-up menuItem.\n"
					+ "Once you click on the Insert Relationship popmenu, you should see 8 small red circles (anchor points) on each class. \n"
					+ "To draw a relationship, you need to click on one of the class's dots/anchor points, and drag your cursor to another class's anchor point (wherever you want to put the relationship).\n"
					+ "Relationships can be moved to different positions on a class.\n"
					+ "You can edit a relationship by either using the Edit menu and selecting (Relationship Inspector), or by right-clicking on the relationship and left-clicking on the (Edit Relationship) pop-up menuItem.\n"
					+ "Once you are in the Relationship Inspector frame, you can change the Type of the relationship.\n"
					+ "A Helpful Note: Editting class methods will effect the LAST RELATIONSHIP CLICKED!!! \n"
					+ "For example: If you click on a relationship, any Editting method (by Edit menu, or right-click), will effect that relationship; even if you right-click anywhere else in the textarea, \n"
					+ "the LAST RELATIONSHIP CLICKED (right-click or left-click), will be editted.\n"
					+ "Small Bug Note: Since the LAST RELATIONSHIP CLICKED is the one editted, if a New Diagram is opened and no new relationship is inserted, a relationship in the previous program WILL BE EFFECTED!!\n"
					+ "Another Note: If a relationship goes from one side of a class, to a side of another class, there is a possibility that the relationship will go through the class (No collision detection).\n"
					+ "Also, if at least 2 relationships are drawn from one class to another, there are instances in which the lines of the relationship appear to be fused together.\n  "
					+ "If the class is moved around, the relationships' lines can be seen.", 
					"Relationship Info", JOptionPane.PLAIN_MESSAGE);
}
	}


	public String saveFileName(String message) throws IOException{
		String filename = " ";
		final JFileChooser jfc = new JFileChooser();
		int returnval = jfc.showSaveDialog(this);
		if(returnval == JFileChooser.APPROVE_OPTION){
			File thefile = jfc.getSelectedFile();
			try{
			String FileName = "";
			BufferedWriter out = new BufferedWriter(new FileWriter(thefile, true));  
			out.write(controller.saveStringGenerator());
			out.flush();
			out.close();
			}catch(Exception e){
				System.err.println("Error: " + e.getMessage());
			}
		}
		
		return (filename);
		
	}

	// borrowed code from the java trail
	// http://download.oracle.com/javase/tutorial/uiswing/examples/components/PopupMenuDemoProject/src/components/PopupMenuDemo.java
	class PopupListener extends MouseAdapter {
		JPopupMenu popup;
		DiagramUserInterface theUserInterface;
		PopupListener(JPopupMenu popupMenu, DiagramUserInterface userInterfaceIn) {
			popup = popupMenu;
			theUserInterface = userInterfaceIn;
		}

		public void mousePressed(MouseEvent e) {
			maybeShowPopup(e);
		}

		public void mouseReleased(MouseEvent e) {
			maybeShowPopup(e);
		}

		private void maybeShowPopup(MouseEvent e) {
			if (e.isPopupTrigger()) {
				int x = e.getX();
				int y = e.getY();
				
				popup.show(e.getComponent(), x, y);
				theUserInterface.updatePopupLoc(x, y);
			}
		}
	}
}
	